using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace kompot_wtf
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class WTF : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public static int ScreenWidth;
        public static int ScreenHeight;
		public bool FullScreen = false;

        public static WTF Instance;
        public static ContentManager ContentMgr;
        public static Random Random = new Random();
        public static Sounds Sounds;

        private Map map = new Map();
        private Player player = new Player();
        private GameHud gameHud = new GameHud();
        private Vector2 middle;

        private Texture2D titleScreen;
        private Texture2D creditsScreen;
        private bool drawCredits = false;
        private float titleScreenSwapInterval = 10.0f;
        private float timeFromLastTitleScreenSwap;

        private List<Zombie> zombies = new List<Zombie>();
        private List<Pikap> pikaps = new List<Pikap>();

        private List<GameObject> deads = new List<GameObject>();

        public void addDead(Vector2 pos)
        {
            GameObject dead = new GameObject();
            dead.Load("Textures//chainsaw");
        }

        public WTF()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            IsMouseVisible = true;

            Instance = this;
        }

        public void ResetZombieRadarStates()
        {
            Zombie.ResetZombieRadarStates(zombies);
        }

        public void SpawnChainsaws()
        {
            for (int i = 0; i < 20; i++)
            {
                Chainsaw pik = new Chainsaw();
                pik.Load(player.Position);
                pikaps.Add(pik);
            }
        }

        public void RegenerateZombies()
        {
            int zombiesToGenerate = 30 - zombies.Count;
            for (int i = 0; i < zombiesToGenerate; i++)
            {
                Zombie z = new Zombie();
                z.Load();
                zombies.Add(z);
            }
        }
        
        private bool removeChainsaws = false;
        public void RemoveAllChainsaws()
        {
            removeChainsaws = true;
        }

        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            ScreenWidth = 800;
            ScreenHeight = 600;
						
            graphics.PreferredBackBufferWidth = ScreenWidth;
            graphics.PreferredBackBufferHeight = ScreenHeight;
            graphics.ApplyChanges();

            middle = new Vector2(400, 300);

            GameObject.ScreenWidth = ScreenWidth;
            GameObject.ScreenHeight = ScreenHeight;

			GameState.state = GameState.State.TITLE_SCREEN;

            base.Initialize();
        }

        protected override void LoadContent()
        {
            ContentMgr = Content;

            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            titleScreen = Content.Load<Texture2D>("Textures//title");
            creditsScreen = Content.Load<Texture2D>("Textures//credits");

            map.Load(ScreenWidth, ScreenHeight);

            player.Load();
            gameHud.Load();

            FullScreenEffects.Load(new Vector2(ScreenWidth, ScreenHeight));

			Sounds = new Sounds(ContentMgr);
			FullScreenEffects.AddEnemyRadar(new Vector2(700, 500));
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                this.Exit();
            }

            switch (GameState.state)
            {
                case GameState.State.TITLE_SCREEN:
                    UpdateTitleScreen(gameTime);
                    Sounds.play_menu();
                    break;

                case GameState.State.THIEF:
                    UpdateGameplay(gameTime);
                    Sounds.play_intro();
                    Sounds.stop_menu();
                    Sounds.pause_waltz();
                    break;


                case GameState.State.PLAYER_ESCAPE:
                    UpdateGameplay(gameTime);
                    Sounds.play_menu();
                    Sounds.stop_intro();
                    Sounds.pause_waltz();
                    break;

                case GameState.State.ZOMBIES_ESCAPE:
                    UpdateGameplay(gameTime);
                    Sounds.stop_intro();
                    Sounds.stop_menu();
                    Sounds.play_waltz();
                    break;

                case GameState.State.GAME_OVER:
                    UpdateGameOver();
                    Sounds.play_deathmusic();
                    Sounds.stop_intro();
                    Sounds.stop_menu();
                    Sounds.pause_waltz();
                    Sounds.pause_steps();
                    break;
            }

            base.Update(gameTime);
        }

        private void UpdateCommon()
        {
            var keyboardState = Keyboard.GetState();
            if (keyboardState.IsKeyDown(Keys.F))
            {
				this.graphics.ToggleFullScreen();
			}
        }

        private void UpdateTitleScreen(GameTime gameTime)
        {
            Sounds.play_menu();

            float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
            timeFromLastTitleScreenSwap += deltaTime;

            if (timeFromLastTitleScreenSwap >= titleScreenSwapInterval)
            {
                drawCredits = !drawCredits;
                timeFromLastTitleScreenSwap = 0.0f;
            }

            var keyboardState = Keyboard.GetState();
            if (keyboardState.IsKeyDown(Keys.Escape))
            {
                GameState.state = GameState.State.THIEF;
                // initialize game
                player.Life = 100.0f;
                gameHud.ResetTimeAlive();
                RegenerateZombies();
            }
            else if (keyboardState.IsKeyDown(Keys.Q))
            {
                this.Exit();
            }

            this.UpdateCommon();
        }

        private void UpdateGameplay(GameTime gameTime)
        {
			float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (removeChainsaws)
            {
                pikaps.Clear();
                removeChainsaws = false;
            }

            if (GameState.state == GameState.State.ZOMBIES_ESCAPE)
            {
                Sounds.pause_menu();
                Sounds.stop_intro();

                if (!Sounds.is_fanfare_playing())
                {
                    Sounds.play_waltz();
                }
            }

            player.Update(deltaTime);

            foreach (Zombie zomb in zombies)
            {
                zomb.Update(deltaTime);
            }

            Zombie.CalcMoves(zombies, player, deltaTime);

            Pikap.CalcCollisions(pikaps, player);

            FullScreenEffects.Update(deltaTime, player);

            if (GameState.state != GameState.State.THIEF)
            {
                gameHud.AddTimeAlive(gameTime.ElapsedGameTime);
            }

            gameHud.UpdateLife(player.Life);

            if (player.Life < 0)
            {
                GameState.state = GameState.State.GAME_OVER;
            }

            this.UpdateCommon();
        }

        private void UpdateGameOver()
        {
            var keyboardState = Keyboard.GetState();
            if (keyboardState.IsKeyDown(Keys.Enter))
            {
				Sounds.stop_deathmusic();
                GameState.state = GameState.State.TITLE_SCREEN;
            }

            this.UpdateCommon();
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            switch (GameState.state)
            {
                case GameState.State.TITLE_SCREEN:
                    DrawTitleScreen();
                    break;

                case GameState.State.THIEF:
                case GameState.State.PLAYER_ESCAPE:
                case GameState.State.ZOMBIES_ESCAPE:
                    DrawGameplay(gameTime);
                    break;

                case GameState.State.GAME_OVER:
                    DrawGameOver();
                    break;
            }

            base.Draw(gameTime);
        }

        private void DrawTitleScreen()
        {
            spriteBatch.Begin();

            var screenToDraw = drawCredits ? creditsScreen : titleScreen;
            spriteBatch.Draw(screenToDraw, Vector2.Zero, Color.White);

            spriteBatch.End();
        }

        private void DrawGameplay(GameTime gameTime)
        {
            map.Draw(GraphicsDevice, spriteBatch, player.Position);
            player.Draw(spriteBatch);

            foreach (Zombie zomb in zombies)
                zomb.Draw(spriteBatch);

            foreach (Pikap pik in pikaps)
                pik.Draw(spriteBatch);

            foreach (GameObject go in deads)
                go.Draw(spriteBatch);

            float lightRadius = 150.0f;
            if (GameState.state == GameState.State.PLAYER_ESCAPE)
                lightRadius = 250.0f;
            if (GameState.state == GameState.State.ZOMBIES_ESCAPE)
                lightRadius = 400.0f;

            FullScreenEffects.DrawLight(GraphicsDevice, lightRadius);
			FullScreenEffects.DrawRadar(GraphicsDevice, player);

            FullScreenEffects.DrawEnemyRadars(GraphicsDevice);

            gameHud.Draw(spriteBatch);
        }

        private void DrawGameOver()
        {
            map.Draw(GraphicsDevice, spriteBatch, player.Position);
            player.Draw(spriteBatch);

            foreach (Zombie zomb in zombies)
                zomb.Draw(spriteBatch);

            foreach (Pikap pik in pikaps)
                pik.Draw(spriteBatch);

            FullScreenEffects.DrawLight(GraphicsDevice, 250.0f);

            FullScreenEffects.DrawDeath(GraphicsDevice);

            gameHud.DrawGameOver(spriteBatch);
        }
    }
}
